/*! ******************************************************************************
 *
 * Created on 2021年9月25日
 *
 * Copyright(c) YuZhou Big Data Laboratory CO.,Ltd, 2022.  All rights reserved.
 *
 *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

package org.yzbdl.lanius.core.plugins.util;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.yzbdl.lanius.core.constant.LocalDir;

public class FileUtils {

    // public static Long lastPoint = 0l; //记住上一次的偏移量
    public static Integer jarNum = 0; // 记住要移除的插件数
    public static Integer libNum = 0; // 记住要移除的依赖数

    // public static String getPath() {
    // File directory = new File("");// 参数为空
    // String courseFile = null;
    // try {
    // courseFile = directory.getCanonicalPath();
    // } catch (IOException e) {
    // // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    // return courseFile;
    // }

    // /**
    // * 插件依赖文件夹名
    // */
    // public static String PLUGIN_FOLDER_NAME = getPath() + File.separator + "plugins";

    // /**
    // * 插件依赖文件夹名
    // */
    // public static String LIBPLUGIN_FOLDER_NAME = getPath() + File.separator +
    // System.getProperty("KETTLE_LIBPLUGIN_FOLDER_NAME", "libplugins");

    /**
     * 获取不带后缀的文件名
     * @param filePath
     * @return
     */
    public static String getName(String filePath) {
        if (null == filePath) {
            return null;
        } else {
            int len = filePath.length();
            if (0 == len) {
                return filePath;
            } else {
                if (isFileSeparator(filePath.charAt(len - 1))) {
                    --len;
                }

                int begin = 0;

                for(int i = len - 1; i > -1; --i) {
                    char c = filePath.charAt(i);
                    if (isFileSeparator(c)) {
                        begin = i + 1;
                        break;
                    }
                }

                return filePath.substring(begin, len);
            }
        }
    }

    /**
     * 文件分隔符判断
     * @param c
     * @return
     */
    public static boolean isFileSeparator(char c) {
        return '/' == c || '\\' == c;
    }

    /**
     * 删除插件及其依赖操作
     *
     * @param delFileInfos
     */
    public synchronized static void delPluginWithLibFile(List<Map<String, String>> delFileInfos) {
        List<String> delInfos = new ArrayList<>();
        for (Map<String, String> fileInfo : delFileInfos) {
            StringBuffer delPath = new StringBuffer();
            if (fileInfo.get("type").equals("plugin")) {
                String folderName = fileInfo.get("folderName");
                delPath.append(LocalDir.PLUGIN + LocalDir.separator + folderName);
            } else {
                delPath.append(LocalDir.LIB_PLUGINS + LocalDir.separator + fileInfo.get("name"));
            }
            if (!OSinfo.MAC && OSinfo.WINDOWS) {
                // 目前做成简单删除，不记录删除成功数
                StringBuffer delRecord = new StringBuffer();
                if (fileInfo.get("type").equals("plugin")) {
                    delRecord.append("rd /s /q \"" + delPath + "\"");
                } else {
                    delRecord.append("del /f /s /q \"" + delPath + "\"");
                }
                delInfos.add(delRecord.toString());
            } else {
                StringBuffer delRecord = new StringBuffer("rm -rf " + delPath);
                delInfos.add(delRecord.toString());
            }
        }
        writeIntoFile(delInfos);
    }

    /**
     * 将delete list内容写入文件
     */
    public static void writeIntoFile(List<String> delInfos) {
        String taskFilePath = "";
        String variable1 = "jarNum=" + jarNum;
        String variable2 = "libNum=" + libNum;
        int posIndex = 10;
        String wrap = "\n";
        if (!OSinfo.MAC && OSinfo.WINDOWS) {
            taskFilePath = LocalDir.BASE + LocalDir.separator + "cleanJar.bat";
            variable1 = "set " + variable1;
            variable2 = "set " + variable2;
            posIndex = 16;
        } else {
            wrap = "\r\n";
            taskFilePath = LocalDir.BASE + File.separator + "cleanJar.sh";
        }
        List<String> variables = new ArrayList<>();
        variables.add(variable1);
        variables.add(variable2);
        replaceFileContentLine(taskFilePath, variables, 1);

        StringBuffer content = new StringBuffer();
        for (String delinfo : delInfos) {
            content.append(delinfo).append(wrap);
        }

        try {
            insert(taskFilePath, posIndex, content.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 修改文件内容
     *
     * @param filePath
     * @param replaceLine
     * @param startLine
     * @return
     */
    private synchronized static void replaceFileContentLine(String filePath, List<String> replaceLine, int startLine) {
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(filePath, "rw");
            int index = 0;
            int lineNum = 0;
            int endLine = replaceLine.size() + startLine;
            String line = null;
            // 记住上一次的偏移量
            long lastPoint = 0;
            while ((line = raf.readLine()) != null) {
                lineNum = lineNum + 1;
                final long ponit = raf.getFilePointer();
                if (lineNum >= startLine && lineNum < endLine) {
                    raf.writeBytes(replaceLine.get(index));
                    index++;
                }
                // 读取一行，指针指到下一行开头。用作写下一行，偏移量的开始。
                lastPoint = ponit;
                raf.seek(lastPoint);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 修改文件内容
     *
     * @param filePath
     * @param replaceContent
     * @param regex
     * @return
     */
    private synchronized static boolean modifyFileContent(String filePath, String replaceContent, String regex) {
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(filePath, "rw");
            String line = null;
            // 记住上一次的偏移量
            long lastPoint = 0;
            while ((line = raf.readLine()) != null) {
                // 读取文件一行，将匹配正则的字符串替换
                final String str = replaceFileContent(line, replaceContent, regex);
                final long ponit = raf.getFilePointer();
                raf.seek(lastPoint);
                raf.writeBytes(str);
                // 读取一行，指针指到下一行开头。用作写下一行，偏移量的开始
                lastPoint = ponit;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return true;
    }

    /**
     * <p>替换匹配正则的内容。</p>
     *
     * @param srcContent     源字符串
     * @param replaceContent 替换内容
     * @param regex          正则表达式
     * @return boolean
     */
    private static String replaceFileContent(String srcContent, String replaceContent, String regex) {

        final Pattern pattern = Pattern.compile(regex);
        final Matcher matcher = pattern.matcher(srcContent);
        final StringBuffer sb = new StringBuffer();
        if (matcher.find()) {
            matcher.appendReplacement(sb, replaceContent);
        }
        return sb.toString();
    }

    /**
     * 插入数据
     *
     * @param fileName
     * @param posDeviation
     * @param insertContent
     * @throws IOException
     */
    public synchronized static void insert(String fileName, long posDeviation, String insertContent)
        throws IOException {
        File tmp = File.createTempFile("tmp", null);
        tmp.deleteOnExit();
        // 使用临时文件保存插入点后的数据
        RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
        FileOutputStream out = new FileOutputStream(tmp);
        FileInputStream in = new FileInputStream(tmp);
        // 获取文件的长度即字节数
        long fileLength = raf.length();
        long pos = fileLength - posDeviation;
        raf.seek(pos);
        // ----------下面代码将插入点后的内容读入临时文件中保存----------
        byte[] bbuf = new byte[64];
        // 用于保存实际读取的字节数
        int hasRead = 0;
        // 使用循环方式读取插入点后的数据
        while ((hasRead = raf.read(bbuf)) > 0) {
            // 将读取的数据写入临时文件
            out.write(bbuf, 0, hasRead);
        }
        // -----------下面代码用于插入内容----------
        // 把文件记录指针重写定位到pos位置
        raf.seek(pos);
        // 追加需要插入的内容
        raf.write(insertContent.getBytes("utf-8"));
        // 追加临时文件中的内容
        while ((hasRead = in.read(bbuf)) > 0) {
            raf.write(bbuf, 0, hasRead);
        }
    }

    // /**
    // * 测试
    // * @param args
    // */
    // public static void main(String[] args) {
    //
    // List<Map<String, String>> delInfos = new ArrayList<>();
    // Map<String, String> delPlugin = new HashMap<>();
    // delPlugin.put("path", "M:\\Source_Code\\Lanius\\lanius-fw-ui\\plugins\\accessoutput\\abcdfg.jar");
    // delPlugin.put("name", "abcdfg.jar");
    // delPlugin.put("type", "plugin");
    // delInfos.add(delPlugin);
    // FileUtils.jarNum += delInfos.size();
    // FileUtils.delPluginWithLibFile(new ArrayList<>(delInfos));
    //
    //
    // List<Map<String,String>> delLibInfos = new ArrayList<>();
    // Map<String,String> delLib = new HashMap<>();
    // delLib.put("path", "M:\\Source_Code\\Lanius\\lanius-fw-ui\\libplugins");
    // delLib.put("name", "aaaa.jar");
    // delLib.put("type", "lib");
    // delLibInfos.add(delLib);
    // Map<String,String> delLib1 = new HashMap<>();
    // delLib1.put("path", "M:\\Source_Code\\Lanius\\lanius-fw-ui\\libplugins");
    // delLib1.put("name", "bbbb.jar");
    // delLib1.put("type", "lib");
    // delLibInfos.add(delLib1);
    // Map<String,String> delLib2 = new HashMap<>();
    // delLib2.put("path", "M:\\Source_Code\\Lanius\\lanius-fw-ui\\libplugins");
    // delLib2.put("name", "cccc.jar");
    // delLib2.put("type", "lib");
    // delLibInfos.add(delLib2);
    //
    // FileUtils.libNum += delLibInfos.size();
    // FileUtils.delPluginWithLibFile(new ArrayList<>(delLibInfos));
    // }

}
